﻿using FileDownloader;
using log4net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace NugetDownloader
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }

        private void FileDownloader_DownloadFileCompleted(object sender, DownloadFileCompletedArgs e)
        {
            System.Threading.Interlocked.Increment(ref finishCount);
            reportFinish(sender as IFileDownloader, e);
            if (Directory.Exists(Properties.Settings.Default.CopyDir))
            {
                try
                {
                    var d = sender as FileDownloader.FileDownloader;
                    if(d.destinationFileName?.EndsWith(".dl") == true)
                    {
                        var newFileName = d.destinationFileName.Substring(0, d.destinationFileName.Length - 3);
                        File.Move(d.destinationFileName, newFileName);
                        File.Copy(newFileName, Path.Combine(Properties.Settings.Default.CopyDir, Path.GetFileName(newFileName)), true);
                    }
                   
                }
                catch (Exception ex)
                {
                    log.Error("", ex);
                }
            }
        }

        private void FileDownloader_DownloadProgressChanged(object sender, DownloadFileProgressChangedArgs e)
        {
            reportStatus(sender as IFileDownloader, e);
        }

        int finishCount = 0;
        int total = 0;
        object locker = new object();
        Dictionary<string, ListViewItem> dicDownloadItems = new Dictionary<string, ListViewItem>();
        Dictionary<IFileDownloader, ListViewItem> downloaders = new Dictionary<IFileDownloader, ListViewItem>();
        ILog log = LogManager.GetLogger(typeof(Form1));

        private void btnStart_Click(object sender, EventArgs e)
        {
            var query = txbQuery.Text.Trim();
            var start = (int)numericUpDown1.Value;
            var end = (int)numericUpDown2.Value;
            Task.Run(() => { download(start, end, query); });
        }

        void uiInvoke(Action action)
        {
            if (this.InvokeRequired)
                this.Invoke(action);
            else
                action.Invoke();
        }

        void reportStart(int page)
        {
            uiInvoke(() =>
            {
                this.lblPage.Text = $"正在下载第{page}页";
            });
        }

        void reportStatus(IFileDownloader downloader, DownloadFileProgressChangedArgs e)
        {
            if (downloaders.ContainsKey(downloader))
            {
                uiInvoke(() =>
                {
                    downloaders[downloader].SubItems[2].Text = DownloadStatus.Downloading.ToString();
                    downloaders[downloader].SubItems[1].Text = e.ProgressPercentage.ToString();
                    downloaders[downloader].BackColor = Color.LightGreen;
                });
            }
        }

        void reportFinish(IFileDownloader downloader, DownloadFileCompletedArgs e)
        {
            if (downloaders.ContainsKey(downloader))
            {
                uiInvoke(() =>
                {
                    downloaders[downloader].SubItems[2].Text = DownloadStatus.Finish.ToString();
                    this.label1.Text = $"{finishCount}/{total}";
                    downloaders[downloader].BackColor = Color.LightGray;
                });
            }
        }

        async Task showDownloadItem(List<string> urls)
        {
            uiInvoke(() =>
            {
                foreach (var url in urls)
                {
                    var lvItem = new ListViewItem(url);

                    lvItem.SubItems.Add("0");
                    lvItem.SubItems.Add(DownloadStatus.Pendding.ToString());
                    dicDownloadItems[url] = lvItem;
                    var fileDownloader = new FileDownloader.FileDownloader();
                    fileDownloader.DownloadProgressChanged += FileDownloader_DownloadProgressChanged;
                    fileDownloader.DownloadFileCompleted += FileDownloader_DownloadFileCompleted;
                    lvDownloadItems.Items.Add(lvItem);
                    downloaders[fileDownloader] = lvItem;
                    lvItem.Tag = fileDownloader;

                    var filename = url.Substring("https://www.nuget.org/api/v2/package/".Length).Replace("/", ".") + ".nupkg.dl";
                    filename = Path.Combine(Application.StartupPath, "Downloads", filename);
                    if(!File.Exists(filename.Substring(0, filename.Length - 3)))
                    {
                        if (File.Exists(filename))
                        {
                            File.Delete(filename);
                        }
                        fileDownloader.DownloadFileAsync(new Uri(url), filename);
                        Console.WriteLine(url);
                    }
                    else
                    {
                        lvItem.SubItems[1].Text = "100";
                        lvItem.SubItems[2].Text = "Exist";
                        lvItem.BackColor = Color.LightGray;
                    }
                }
            });
        }

        async Task download(int start, int end, string query)
        {
            var spider = new Spider.Spider();
            

            for (int i = start; i < end; i++)
            {
                try
                {
                    reportStart(i);
                    var result = await spider.GetPackageDownloadUrls(query, i);
                    lock (locker)
                    {
                        total += result.Count;
                    }
                    await showDownloadItem(result);
                }
                catch (Exception ex)
                {
                    log.Error("", ex);
                }
               
            }
        }
    }
}
